package ray.surface;

import ray.math.Point3;
import ray.math.Ray;
import ray.math.Vector3;

/**
 * Represents a sphere as a center and a radius.
 *
 * @author ags
 */
public class Sphere extends Surface {
	
	/** The center of the sphere. */
	protected final Point3 center = new Point3();
	public void setCenter(Point3 center) { this.center.set(center); }
	
	/** The radius of the sphere. */
	protected double radius = 1.0;
	public void setRadius(double radius) { this.radius = radius; }
	
	public Sphere() { }
	
	/**
	 * @see Object#toString()
	 */
	public String toString() {
		return "sphere " + center + " " + radius + " " + shader + " end";
	}
	
	//If the ray intersects this Sphere, then this function returns the t
	//value of the intersection. Otherwise, it returns 0. "direction" must
	//be a unit vector for this function to work!
	public double rayCollision(Vector3 direction,Point3 viewPoint){
		double t;
		
		Vector3 pC = new Vector3();
		pC.sub(center,viewPoint);
		double tC = direction.dot(pC);
		Point3 xC = new Point3(viewPoint.x,viewPoint.y,viewPoint.z);
		xC.scaleAdd(tC, direction);
		Vector3 d = new Vector3();
		d.sub(xC, center);
		if(d.length()>radius){
			return 0.0;
		}
		else{
			double a = Math.sqrt((radius*radius) - d.lengthsquared());
			t = tC-a;
			if(t<=0){
				t=tC+a;
				if(t<=0){
					return 0;
				}
			}
		}
	
		return t;
	}
	
	public double rayCollision(Ray ray){
		return rayCollision(ray.direction,ray.origin);
	}
	
	public Vector3 calcUnitNormal(Point3 point){
		Vector3 unitNormal = new Vector3();
		unitNormal.sub(point, center);
		unitNormal.normalize();
		return unitNormal;
	}
}
